﻿using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UMLSynthesizer.CSharpAnalyzer.Helpers;
using UMLSynthesizer.CSharpAnalyzer.Statements;
using UMLSynthesizer.LangAnalyzer;
using UMLSynthesizer.LangAnalyzer.Elements;
using UMLSynthesizer.LangAnalyzer.ExtensionMethods;
using UMLSynthesizer.LangAnalyzer.Statements;

namespace UMLSynthesizer.CSharpAnalyzer.Elements
{
    class CSharpMethodElement : IMethodElement
    {
        #region Fields

        MethodDeclarationSyntax elementNode;
        CSharpElementWithParametersHelper parametersHelper;
        CSharpElementWithAttributesHelper attributesHelper;

        #endregion

        #region Constructor

        public CSharpMethodElement(MethodDeclarationSyntax elementNode, IElementBase parentElement)
        {
            if (elementNode == null)
                throw new ArgumentNullException("elementNode");
            if (parentElement == null)
                throw new ArgumentNullException("parentElement");

            this.elementNode = elementNode;
            this.ParentElement = parentElement;
            this.ProjectOwner = parentElement.ProjectOwner;
            this.parametersHelper = new CSharpElementWithParametersHelper(this, elementNode);
            this.attributesHelper = new CSharpElementWithAttributesHelper(elementNode);

            this.MetricDictionary = new Dictionary<LanguageAnalyzer.Metrics, double>();
        }

        #endregion

        #region Properties

        public string Identifier { get { return elementNode.Identifier.ToString(); } }
        public ElementKinds Kind { get { return ElementKinds.Method; } }
        public IElementBase ParentElement { get; private set; }
        public IProjectElement ProjectOwner { get; private set; }

        public IBlockStatement Body
        {
            get
            {
                if (elementNode.Body == null)
                    return null;
                return new CSharpBlockStatement(elementNode.Body, null, this);
            }
        }

        public ITypeBase Type { get { return (ProjectOwner as CSharpProjectElement).GetTypeReference(elementNode.ReturnType); } }
        public IEnumerable<IParameterElement> ParameterList { get { return parametersHelper.ParameterList; } }

        public bool IsAbstract { get { return attributesHelper.IsAbstract; } }
        public bool IsStatic { get { return attributesHelper.IsStatic; } }
        public VisibilityStates Visibility { get { return attributesHelper.Visibility; } }

        public Dictionary<LanguageAnalyzer.Metrics, double> MetricDictionary { get; private set; }

        #endregion
    }
}
